package com.fakeofarty;

import java.util.ArrayList;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;

public class LocationService extends Service {

	private final IBinder mBinder = new LocalBinder();

	float mDelta = 5;

	float mDistance = 0;
	long mTime = 0;
	long mStartTime = 0;
	boolean mStarted = false;
	boolean mGpsStatus = false;
	LocationManager mLocationManager;// = (LocationManager)
										// this.getSystemService(Context.LOCATION_SERVICE);
	Location mLastLocation = null;
	Location mCurrentLocation = null;

	ArrayList<WayPoint> mPath = new ArrayList<WayPoint>();
	ArrayList<WayPoint> mBackPoint = new ArrayList<WayPoint>();
	ArrayList<WayPoint> mCheckPoint = new ArrayList<WayPoint>();

	GpsStatus.Listener mGPSListener = new GpsStatus.Listener() {
		public void onGpsStatusChanged(int event) {
			switch (event) {
			case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
				if (mLastLocation != null)
					mGpsStatus = (System.currentTimeMillis() - mTime - mStartTime) < 3000;
				else
					mGpsStatus = false;
				break;
			case GpsStatus.GPS_EVENT_FIRST_FIX:
				mGpsStatus = true;
				break;
			case GpsStatus.GPS_EVENT_STOPPED:
				mGpsStatus = false;
				break;
			}
		}
	};

	void newPoint(int type, int id) {
		if (mCurrentLocation == null)
			return;
		if (mLastLocation != null)
			mDistance += mCurrentLocation.distanceTo(mLastLocation);
		mLastLocation = mCurrentLocation;
		mPath.add(new WayPoint(mCurrentLocation, 0));
		if (type == WayPoint.TYPE_BACK)
			mBackPoint.add(new WayPoint(mCurrentLocation, 0));
		if (type == WayPoint.TYPE_CHECK)
			mCheckPoint.add(new WayPoint(mCurrentLocation, id));
	}

	// Define a listener that responds to location updates
	LocationListener mLocationListener = new LocationListener() {
		@Override
		public void onLocationChanged(Location location) {
			if (!mStarted)
				return;
			mCurrentLocation = location;
			mTime = System.currentTimeMillis() - mStartTime;
			if (mLastLocation == null
					|| location.distanceTo(mLastLocation) > mDelta) {
				newPoint(WayPoint.TYPE_USUAL, 0);
			}
		}

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
			// mGpsStatus = (status == LocationProvider.AVAILABLE);
		}

		@Override
		public void onProviderEnabled(String provider) {
		}

		@Override
		public void onProviderDisabled(String provider) {
		}
	};

	public class LocalBinder extends Binder {
		LocationService getService() {
			return LocationService.this;
		}
	}

	@Override
	public IBinder onBind(Intent intent) {
		mLocationManager = (LocationManager) this
				.getSystemService(Context.LOCATION_SERVICE);
		mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
				0, 0, mLocationListener);
		mLocationManager.addGpsStatusListener(mGPSListener);
		return mBinder;
	}

	@Override
	public void onDestroy() {
		if (mStarted)
			stop();
		mLocationManager.removeUpdates(mLocationListener);
		mLocationManager.removeGpsStatusListener(mGPSListener);
	};

	public void start() {
		mDistance = 0;
		mStartTime = System.currentTimeMillis();
		mTime = 0;
		mStarted = true;
	}

	void savePath() {
		KMLCreator xml_file = new KMLCreator();
		xml_file.create();
		xml_file.writePath(mPath);
		xml_file.writeCheckpoints(mCheckPoint);
		xml_file.writeBackPoints(mBackPoint);
		xml_file.saveXML();
	}

	public void stop() {
		savePath();
		mStarted = false;
	}

	public Point getLastPoint(int type, int id) {
		switch (type) {
		case WayPoint.TYPE_BACK:
			newPoint(WayPoint.TYPE_BACK, id);
			break;
		case WayPoint.TYPE_USUAL:
			break;
		case WayPoint.TYPE_CHECK:
			newPoint(WayPoint.TYPE_CHECK, id);
			break;
		}
		if (mLastLocation == null) {
			return new Point(mTime, 0, 0);
		}
		return new Point(mTime, mDistance
				+ mCurrentLocation.distanceTo(mLastLocation),
				(mCurrentLocation.getSpeed() + mLastLocation.getSpeed()) / 2);
	};

	public boolean getGpsStatus() {
		return mGpsStatus;
	}

}
